package com.da.landlord;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Filter;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.cswish.annotation.Rest;
import com.googlecode.cswish.exception.ApplicationException;
import com.googlecode.cswish.model.PageInfo;
import com.googlecode.cswish.model.Reference;
import com.googlecode.cswish.oosearch.Condition;
import com.googlecode.cswish.oosearch.QLInfo;
import com.googlecode.cswish.struts.spring.GenericService;
import com.googlecode.cswish.struts.spring.ObjectFactory;
import com.ra.landlord.Building;
import com.ra.landlord.BuildingFloor;
import com.ra.landlord.Fee;
import com.ra.landlord.FeeAddition;
import com.ra.landlord.FeeAdditionRecord;
import com.ra.landlord.FeeRecord;
import com.ra.landlord.FeeRecordService;
import com.ra.landlord.FeeRuleCfg;
import com.ra.landlord.FeeRuleCfgDesc;
import com.ra.landlord.LandlordOwnerUser;
import com.ra.landlord.LandlordUser;
import com.ra.landlord.LandlordUserService;
import com.ra.landlord.Meter;
import com.ra.landlord.Room;
import com.ra.landlord.RoomService;
import com.ra.landlord.TenantUser;
import com.ra.landlord.ValidAgreement;
import com.ra.landlord.constant.FeeRuleType;
import com.ra.landlord.constant.LandlordConstant;
import com.ra.order.OrderUtil;
import com.ra.order.rental.RentalOrder;
import com.ra.order.rental.RentalOrderService;
import com.ra.util.DateTimeUtil;

/**
 * 资金确认
 * @author PeterZ
 *
 */
@Service
public class DaConfirmMoneyService {

	private static final Log logger = LogFactory.getLog(DaConfirmMoneyService.class);

	@PersistenceContext(unitName="espirit")
	protected EntityManager em;
	
	@Resource
	private GenericService genericService;
	
	@Resource
	private RoomService roomService;
	
	@Resource
	private DaSuiteService daSuiteService;
	
	@Resource
	private RentalOrderService rentalOrderService;
	
	@Resource
	private PaidNoticeService paidNoticeService;
	
	@Resource
	private DaChargeItemService daChargeItemService;
	
	@Resource
	private FeeRecordService feeRecordService;
	
	@Resource
	private LandlordUserService landlordUserService;
	
	
	private DaConfirmMoneyService daConfirmMoneyService;
	
	
	public DaConfirmMoneyService getInstance(){
		if (daConfirmMoneyService == null){
			daConfirmMoneyService = ObjectFactory.getInstance().getBean(DaConfirmMoneyService.class,false);
		}
		return daConfirmMoneyService;
	}
	
	public void view(){
		return ;
	}
	
	/**
	 * 查询未收租的 room 包括应收费用
	 * 真接调用roomService里面的相同接口。
	 * @param model
	 * @param start
	 * @param limit
	 * @param sort
	 * @param dir
	 * @param oldSearch
	 * @param qlInfoRef
	 * @return
	 */
	@Rest(type = "search")
	public VOBase  searchWithFee(Room model, int start, int limit,
    		String sort, String dir, boolean oldSearch, Reference<QLInfo> qlInfoRef,String userName,Integer status,boolean isFirst){
		
		setSearchCondition(model,isFirst);
		
		List<Room> dbRooms = searchRentedRoomsWithOrderStatusAnd(model,status,userName);
		
		List<ConfirmMoneyVO> resultVO  = new ArrayList<ConfirmMoneyVO>();
		if(null != dbRooms){
			for (Room room : dbRooms) {
				
				room.setHasPay(null);
				room = roomService._collectRental(room);
				
				RentalOrder hasOrder = null;
				Fee fee = room.getReceivableFee();
				if(fee==null)continue;
				//查询当前record是否有生成的定单
				FeeRecord feeRecordExample = new FeeRecord();
				feeRecordExample.setId(fee.getFeeRecordId());
				hasOrder = rentalOrderService.searchRentalOrderByFeeRecord(feeRecordExample);
				if(status==2){
					//脏数据 
					if( hasOrder==null){
						continue;
					}
				}else if (status==1){
					RentalOrder roomLastOrder = getRoomLastPaidOrder(room);
					if(roomLastOrder==null){
						continue;
					}else{
						hasOrder = roomLastOrder;
						FeeRecord feeRecord = hasOrder.getFeeRecord();
						if(room.getAgreement().getFees().size()==2){
							fee = setPaidOrderDeposit(room, fee);
						}else{
							if(feeRecord!=null){
								feeRecordService.copyFeeRecord2Fee(feeRecord, fee);
								BigDecimal prevBalance = feeRecord.getPrevBalance();
								if(prevBalance!=null){
									fee.setPrevBalance(prevBalance);
								}else{
									//兼容老数据代码  （当代码执行到这里肯定fees.size>=2的，因为已交箐成功）
									if(room.getAgreement().getFees().size()<2)continue;
									prevBalance = room.getAgreement().getFees().get(1).getBalance();
									if(prevBalance!=null){
										fee.setPrevBalance(prevBalance);
										feeRecord.setPrevBalance(prevBalance);
									}else{
										fee.setPrevBalance(BigDecimal.valueOf(0));
									}
								}
							}else{
								continue;
							}
						}
					}
				}else if(status==0 && hasOrder != null){
					continue;
				}
				
				if(hasOrder!=null && fee !=null){
					setRentalCalc(fee);
				}
				
				//存放未转换的收费项
				List<FeeAddition>  items = fee.getFeeAdditions()==null?new ArrayList<FeeAddition>():fee.getFeeAdditions();
				//存放转换过后的收费项
				List<ConfirmMoneyItemVO> voItems = new ArrayList<ConfirmMoneyItemVO>();
				//转换
				for (FeeAddition feeAddition : items) {
					ConfirmMoneyItemVO voItem = getVoItem(feeAddition,fee);
					if(voItem != null){
						voItems.add(voItem);
					}
				}
				//封装结果集
				ConfirmMoneyVO vo = getVo(room,voItems,hasOrder,fee);
				resultVO.add(vo); 
			}
		}
		VOBase base = getVOBase(model, dbRooms, resultVO);
		return base;
	}

	private Fee setPaidOrderDeposit(Room room, Fee fee) {
		fee.setPrevBalance(BigDecimal.valueOf(0));
		room.setNeedAddDeposit(true);
		//租金
		fee = room.getAgreement().getFees().get(0);
		//押金
		Fee yj = room.getAgreement().getFees().get(1);
		BigDecimal sumActual = fee.getAmountActual().add(yj.getAmountActual());
		BigDecimal sumRecv = fee.getAmountRecv().add(yj.getAmountActual());
		fee.setAmountActual(sumActual);
		fee.setAmountRecv(sumRecv);
		fee.setDepositActual(yj.getAmountActual());
		return fee;
	}

	
	/**
	 * 查询当前的record是否已生成网上收租单
	 * @param recordId
	 * @return
	 */
	private RentalOrder searchOrderby(Integer recordId) {
		RentalOrder hasOrder;
		FeeRecord record = new FeeRecord();
		record.setId(recordId);
		hasOrder = rentalOrderService.readRentalOrderInfo(record);
		return hasOrder;
	}

	
	/**
	 * 调用出租接口使之产生费用
	 * @param dbRooms
	 * @return
	 */
	private List<Room> setRoomsFee(List<Room> dbRooms,Integer status) {
		List<Room> rooms = new ArrayList<Room>();
		if (dbRooms != null) {
			for (Room room : dbRooms) {
				if (room.getRentState() == Room.RENT_STATE_ALREADY) {
					//安全性检查
					if(room.getAgreement()==null)continue;
					//已交租时不能出现未交租的房间 未生成里不能出现已交租的房间
					if(room.getHasPay() && status == 0){
						continue;
					}
					if(status == 2){
						room.setHasPay(null);
					}
					room = roomService._collectRental(room);
					rooms.add(room);
				}
			}
		}
		return rooms;
	}

	
	/**
	 * 封装查询条件
	 * @param model
	 * @param limit
	 * @param userName
	 * @param isFirst
	 */
	private void setSearchCondition(Room model,boolean isFirst) {
		
		model.setHasRent(true);
		model.setHasPay(false);
		
		//条件查询1  如果为首次进入，默认显示第一层的楼房 否则根据传入的楼层参数进行选取
		if( model.getBuildingFloor()!=null && (isFirst&&model.getBuildingFloor().getId()==null) ){
			BuildingFloor firstFloor = getfirstFloor(model);
			model.setBuildingFloor(firstFloor);
		} 
		//条件查询2   楼层查询
		if(model.getBuildingFloor()==null){
				BuildingFloor floor = new BuildingFloor();
				floor.setId(0);
				model.setBuildingFloor(floor);
		}
	}

	
	/**
	 * 设置房租的计算应收
	 * @param fee
	 */
	private void setRentalCalc(Fee fee) {
		Room dbRoom = fee.getRoom();
		int monthCycle = dbRoom.getAgreement().getRentCycle() + 1;
		//判断是否为第一笔租金  第一笔处理是不一样的。
		if (dbRoom.getAgreement().getFees() == null || dbRoom.getAgreement().getFees().size() <= 1) {
			if (dbRoom.getPayNum() != null) {
				monthCycle = dbRoom.getPayNum();
			}
		}
		 if (dbRoom.getRental() != null) {
			fee.setRentalCalc(BigDecimal.valueOf(Double.valueOf(dbRoom.getRental())));
		} else {
			fee.setRentalCalc(dbRoom.getAgreement().getRentPay());
		}
		fee.setRentalCalc(fee.getRentalCalc().multiply(BigDecimal.valueOf(monthCycle)).setScale(2, RoundingMode.HALF_UP));
	}

	
	/**
	 * 封装VOBase
	 * @param model
	 * @param rooms 楼层所拥有的房间
	 * @param resultVO 封装好的所有房间
	 * @return
	 */
	private VOBase getVOBase(Room model, List<Room> rooms,
			List<ConfirmMoneyVO> resultVO) {
		VOBase base = new VOBase();
		base.setRooms(resultVO);
		//整层楼一个房间都没有
		if(rooms==null ||rooms.size()==0){
			Building building = new Building();
			building.setId(model.getBuilding().getId());;
			building = genericService.view(building);
			Integer floorCount = building.getFloorCount();
			base.setFloorCount(floorCount);
			base.setFloors(building.getBuildingFloors());
		}else{
			base.setFloorCount(rooms.get(0).getBuilding().getBuildingFloors().size());//总楼层数
			base.setFloors(rooms.get(0).getBuilding().getBuildingFloors());
		}
		//页面必须传入参数
		try{
			base.setCurrFloor(model.getBuildingFloor().getId());
		}catch(Exception e){
			base.setCurrFloor(0);
		}
		return base;
	}

	
	/**
	 * 获取楼房的第一层floor对象
	 * @param model
	 */
	private BuildingFloor getfirstFloor(Room model) {
		Integer buildingId = model.getBuilding().getId();
		String ql = " from "+BuildingFloor.class.getName()+" a where 1=1";
		QLInfo qlInfo = new QLInfo();
		ql += " and a.building is not null and a.building.id = ? ";
		qlInfo.addParam(buildingId);
		qlInfo.setQl(ql);
		qlInfo.setMaxResults(1);
		qlInfo.setPageInfo(0, 1, "id", "asc");
		@SuppressWarnings("unchecked")
		List<BuildingFloor> floors = genericService.searchByQl(qlInfo).getData();
		BuildingFloor floor = floors.get(0);
		return floor;
	}
	
	
	/**
	 * 获取房间最后一笔收租记录  集中式
	 * @param ConvenientRentalOrder
	 * @return
	 */
	private RentalOrder getRoomLastPaidOrder(Room room) {
		QLInfo qlInfo = new QLInfo("select a from " + RentalOrder.class.getName() + " a where a.feeRecord.agreement = ? and ( a.orderState = ? or a.orderState = ? )", false, room.getAgreement(), RentalOrder.ORDER_STATE_PAYMENTED, RentalOrder.ORDER_STATE_SUCCESS);
		qlInfo.setCompiledSort("a.id");
		qlInfo.setDir("desc");
		return (RentalOrder) genericService.searchByQl(qlInfo).getData(0);
	}


	/**
	 * 获取房间最后一笔收租记录  分散式
	 * @param ConvenientRentalOrder
	 * @return
	 */
	private RentalOrder getDaRoomLastPaidOrder(DaRoom daRoom) {
		DaChargeBillRecord parmRecord = new DaChargeBillRecord();
		parmRecord.setAgreement(daRoom.getAgreement());
		RentalOrder hasOrder;
		hasOrder = new RentalOrder();
		hasOrder.setOrderState(RentalOrder.ORDER_STATE_SUCCESS);
		hasOrder.setChargeBillRecord(parmRecord);
		Condition condition = new Condition();
		condition.setDir("desc");
		condition.setSort("id");
		PageInfo<RentalOrder> searchByModel = genericService.searchByModel(hasOrder, condition);
		hasOrder = searchByModel.getData(0);
		return hasOrder;
	}
	
	
	/**
	 * 分散式，生成网上定单
	 * @param vos
	 * @param isUpdate 是否为修改
	 * @return
	 */
	@Transactional
	public Integer confirmMoneyForDa(List<ConfirmMoneyVO> vos){
		if(vos==null || vos.size() ==0 )return 0;
		for (ConfirmMoneyVO confirmMoneyVO : vos) {
			
			//实收总额
			BigDecimal amountActual = confirmMoneyVO.getTotalPriceTrue();
			//应收总额
			BigDecimal amountRecv = confirmMoneyVO.getTotalPrice();
			amountActual = amountActual==null?amountRecv:amountActual;
			if(amountActual==null){
				amountActual = BigDecimal.valueOf(0);
			}
			// 防止信用卡恶意套现金额限制
			rentalOrderService.creditCardIntercept(amountActual);
			
			DaChargeBillRecord record = new DaChargeBillRecord();
			record.setId(confirmMoneyVO.getFeeRecordId());
			DaChargeBillRecord dbrecord = genericService.load(record);
			if(dbrecord == null )continue;
			
			RentalOrder order = searchDaOrderBy(dbrecord);
			
			if(order!=null){
				if(order.getOrderState()!=null && !order.getOrderState().equals(RentalOrder.ORDER_STATE_WAITING_PAYMENT)){
					throw new ApplicationException("提示：正在支付中或已交租成功，不能再次生成！！");
				}
				order.setRoomType(LandlordConstant.ROOMTYPE_DA);
				order.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
				order.setOrderState(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
				dbrecord = order.getChargeBillRecord();
				DaRoom daRoom = genericService.load(DaRoom.class,confirmMoneyVO.getId());
				
				LandlordOwnerUser landlordUser = landlordUserService.getLandlordOwnerUser();
				order.setCreateUser(landlordUser);
				
				// 设置租客
				if(dbrecord != null && dbrecord.getAgreement() != null 
						&& dbrecord.getAgreement().getTenantUser() != null) {
					order.setTenantUser(dbrecord.getAgreement().getTenantUser());
				}
				
				dbrecord.setPrevBalance(paidNoticeService.getRoomBlance(daRoom));
				genericService.merge(order);
			}else{
				createNewDaOrder(confirmMoneyVO, dbrecord);
			}
		}
		return 1;
	}

	
	/**
	 * 分散式
	 * 创建一个网上收租单
	 * @param confirmMoneyVO
	 * @param dbrecord
	 */
	private void createNewDaOrder(ConfirmMoneyVO confirmMoneyVO,
			DaChargeBillRecord dbrecord) {
		RentalOrder order = new RentalOrder();
		order.setChargeBillRecord(dbrecord);
		order.setDaRoom(dbrecord.getRoom());
		order.setRoomType(LandlordConstant.ROOMTYPE_DA);
		order.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		order.setOrderState(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
		Date date = new Date();
		order.setCreateTime(new Timestamp(date.getTime()));
		String outTradeNo = OrderUtil.getOrderNum();
		order.setOutTradeNo(outTradeNo);
		order.setShowURL("");
		String startDate = confirmMoneyVO.getStartDate();
		String endDate = confirmMoneyVO.getEndDate();
		// 订单名称
		String orderName =confirmMoneyVO.getName()+"("+startDate+"~"+endDate+")总费用";//收费周期
		order.setOrderName(orderName);
		
		//实收总额
		BigDecimal amountActual = confirmMoneyVO.getTotalPriceTrue();
		//应收总额
		BigDecimal amountRecv = confirmMoneyVO.getTotalPrice();
		amountActual = amountActual==null?amountRecv:amountActual;
		if(amountActual==null){
			amountActual = BigDecimal.valueOf(0);
		}
		//总费用
		order.setTotalFee(amountActual);
		
		//设置状态为待付款
		order.setChargeItems(dbrecord.getChargeItems());
		
		// 设置租客
		if(dbrecord != null && dbrecord.getAgreement() != null 
				&& dbrecord.getAgreement().getTenantUser() != null) {
			order.setTenantUser(dbrecord.getAgreement().getTenantUser());
		}
		LandlordOwnerUser landlordUser = landlordUserService.getLandlordOwnerUser();
		order.setCreateUser(landlordUser);
		
		DaRoom daRoom = genericService.load(DaRoom.class,confirmMoneyVO.getId());
		dbrecord.setPrevBalance(paidNoticeService.getRoomBlance(daRoom));
		
		genericService.merge(order);
	}
	
	
	/**
	 * 分散式
	 * 判断是新增还是修改
	 * @param record
	 * @return
	 */
	private RentalOrder searchDaOrderBy(DaChargeBillRecord record) {
		RentalOrder order = new RentalOrder();
		order.setChargeBillRecord(record);
		PageInfo<RentalOrder> searchByModel = genericService.searchByModel(order,Condition.DEFAULT);
		List<RentalOrder> data = searchByModel.getData();
		if(data!=null && data.size()>0){
			return data.get(0);
		}
		return null;
	}
	
	/**
	 * 分散式
	 * 得到上一个已支付定单信息
	 * @param daRoom
	 * @return
	 */
	public RentalOrder getPrevRentalOrder(DaRoom daRoom){
		List<DaChargeBillRecord> chargeBillRecords = daRoom.getAgreement().getChargeBillRecords();
		DaChargeBillRecord prevRecord = null;
		if(chargeBillRecords!= null && chargeBillRecords.size()>1){
			prevRecord = chargeBillRecords.get(1);
			
			RentalOrder prevOrder = new RentalOrder();
			prevOrder.setChargeBillRecord(prevRecord);
			PageInfo<RentalOrder> searchByModel = genericService.searchByModel(prevOrder, Condition.DEFAULT);
			List<RentalOrder> allOrder = searchByModel.getData();
			if(allOrder != null && allOrder.size() > 0 ){
				return allOrder.get(0);
			}else{
				prevRecord = chargeBillRecords.get(0);
				prevOrder = new RentalOrder();
				prevOrder.setChargeBillRecord(prevRecord);
				 searchByModel = genericService.searchByModel(prevOrder, Condition.DEFAULT);
				 allOrder = searchByModel.getData();
				 if(allOrder != null && allOrder.size() > 0 ){
						return allOrder.get(0);
				 }else{
					 return null;
				 }
			}
			
		}else{
			return null;
		}
		
	}
	
	
	/**
	 * 集中式，生成网上定单
	 * @param vos
	 * @param status 表示是重新生成，还是首次生成
	 * @return
	 */
	public Integer confirmMoneyForRa(List<ConfirmMoneyVO> vos,Integer status){
			for (ConfirmMoneyVO vo : vos) {
				RentalOrder dborder = searchOrderby(vo.getFeeRecordId());
				
				BigDecimal amountRecv = vo.getTotalPrice();
				BigDecimal amountActul = vo.getTotalPriceTrue();
				amountActul = amountActul==null?amountRecv:amountActul;
				rentalOrderService.creditCardIntercept(amountActul);
				
				//正在支付中的不能再次确认
				if(dborder!=null &&dborder.getOrderState()!=null && !dborder.getOrderState().equals(RentalOrder.ORDER_STATE_WAITING_PAYMENT)){
					throw new ApplicationException("提示：正在支付中或已交租成功，不能再次生成！！");
				}else if(dborder!=null &&dborder.getOrderState()!=null && dborder.getOrderState().equals(RentalOrder.ORDER_STATE_WAITING_PAYMENT)){
					genericService.delete(dborder);
				}
				RentalOrder order = getRentalOrder(vo);
				rentalOrderService.addRentalOrder(order, null);
			}
		return 1;
	}
	
	
	/**
	 *集中式, 来自收租页面的生成网上定单
	 * @param model
	 * @param extraFee
	 * @param depositRecv
	 * @param depositActual
	 */
	@Rest(type = "update")
	public RentalOrder confirmMoneyFromCollectForRa(Fee model, List<FeeAddition> extraFee, BigDecimal depositRecv, BigDecimal depositActual) {
		if( model.getFeeRecordId() == null)return null;
		
		//注入检查
		rentalOrderService.creditCardIntercept(model.getAmountActual());

		RentalOrder order = searchOrderby(model.getFeeRecordId());
		FeeRecord record = new FeeRecord();
		//正在支付中的不能再次确认
		if(order!=null && order.getOrderState()!=null && !order.getOrderState().equals(RentalOrder.ORDER_STATE_WAITING_PAYMENT)){
			throw new ApplicationException("提示：正在支付中或已交租成功，不能再次生成！！");
		}else if(order!=null && order.getOrderState()!=null && order.getOrderState().equals(RentalOrder.ORDER_STATE_WAITING_PAYMENT)){
			genericService.delete(order);
		}
		order = setFeeRecord(model, order, record,extraFee,depositRecv,depositActual);
		return rentalOrderService.addRentalOrder(order, null);
	}

	/**
	 * 分散式,来自收租页面的生成网上定单
	 * @param models
	 * @param extraFee
	 * @param roomId
	 * @param amountRecv
	 * @param amountActual
	 * @param remark
	 * @param dateBeginRecv
	 * @param dateEndRecv
	 * @return
	 */
	@Rest(type = "update")
	public DaChargeBillRecord confirmMoneyFromCollectForDa(List<DaChargeItem> models, List<DaChargeItem> extraFee, Integer roomId, BigDecimal amountRecv, BigDecimal amountActual, String remark, Date dateBeginRecv, Date dateEndRecv,BigDecimal balance){
		DaRoom dbRoom = genericService.load(DaRoom.class, roomId);
		if (dbRoom == null) {
			throw new ApplicationException("房间找不到，资金确认失败!！");	
		}
		DaChargeBillRecord dbChargeBillRecord = daChargeItemService.getOrGenerateChargeBillRecord(dbRoom);
		RentalOrder order = searchDaOrderBy(dbChargeBillRecord);
		
		if(order!=null){
			if(order.getOrderState()!=null && !order.getOrderState().equals(RentalOrder.ORDER_STATE_WAITING_PAYMENT)){
				throw new ApplicationException("提示：正在支付中或已交租成功，不能再次生成！！");
			}
			dealRentalOrder(models,extraFee, amountRecv, amountActual, dateBeginRecv,
					dateEndRecv, dbRoom, dbChargeBillRecord, order,balance,remark);
		}else{
			order = new RentalOrder();
			dealRentalOrder(models,extraFee, amountRecv, amountActual, dateBeginRecv,
					dateEndRecv, dbRoom, dbChargeBillRecord, order ,balance,remark);
		}
		return dbChargeBillRecord;
	}

	
	/**
	 * 分散式 生成网上定单处理rentalOrder 
	 * 生成网上定单
	 * @param models
	 * @param amountRecv
	 * @param amountActual
	 * @param dateBeginRecv
	 * @param dateEndRecv
	 * @param dbRoom
	 * @param dbChargeBillRecord
	 * @param order
	 */
	@Transactional
	private void dealRentalOrder(List<DaChargeItem> models,List<DaChargeItem> extraFee,
			BigDecimal amountRecv, BigDecimal amountActual, Date dateBeginRecv,
			Date dateEndRecv, DaRoom dbRoom,
			DaChargeBillRecord dbChargeBillRecord, RentalOrder order,BigDecimal balance,String remark) {
		
		order.setDaRoom(dbRoom);
		order.setRoomType(LandlordConstant.ROOMTYPE_DA);
		order.setOrderState(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
		order.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		Date date = new Date();
		order.setCreateTime(new Timestamp(date.getTime()));
		String outTradeNo = OrderUtil.getOrderNum();
		order.setOutTradeNo(outTradeNo);
		order.setShowURL("");
		String startDate = getDataStr(dateBeginRecv);
		String endDate = getDataStr(dateEndRecv);
		
		// 防止信用卡恶意套现金额限制
		rentalOrderService.creditCardIntercept(amountActual);
		
		order.setTotalFee(amountActual);
		
		DaSuite suite = dbRoom.getSuite();
		if(suite.getRentType().equals(DaSuite.RENT_TYPE_ENTIRE)){
			order.setOrderName(suite.getName()+"("+startDate+"~"+endDate+")总费用");
		}else{
			order.setOrderName(suite.getName()+"-"+dbRoom.getName()+"("+startDate+"~"+endDate+")总费用");
		}
		
		order.setChargeBillRecord(dbChargeBillRecord);
		
		dbChargeBillRecord.setAmountRecv(amountRecv);
		dbChargeBillRecord.setAmountActual(amountActual);
		dbChargeBillRecord.setDateBeginRecv(dateBeginRecv);
		dbChargeBillRecord.setDateEndRecv(dateEndRecv);
		dbChargeBillRecord.setRemark(remark);
		
		LandlordOwnerUser landlordUser = landlordUserService.getLandlordOwnerUser();
		order.setCreateUser(landlordUser);
		// 设置租客
		if(dbChargeBillRecord != null && dbChargeBillRecord.getAgreement() != null 
						&& dbChargeBillRecord.getAgreement().getTenantUser() != null) {
			order.setTenantUser(dbChargeBillRecord.getAgreement().getTenantUser());
		}
		
		//余额 
		if(	balance == null  ){
			balance = amountActual.subtract(amountRecv).setScale(2, RoundingMode.HALF_UP);
		}
		dbChargeBillRecord.setPrevBalance(paidNoticeService.getRoomBlance(dbRoom));
		
		dbChargeBillRecord.setBalance(balance.setScale(2, RoundingMode.HALF_UP));
		genericService.merge(order);
		
		List<DaChargeItem> dbChargeItems = new ArrayList<DaChargeItem>();
		for (DaChargeItem daChargeItem : models) {
			DaChargeItem dbitem = genericService.load(daChargeItem);
			
			if (dbitem.getChargeType() <= 1) {	//目前为了跟ra统一，分散式也不支持押金和租金的勾选。
				dbitem.setStatus(DaChargeItem.STATUS_CONFIRMED);	
			}else{
				dbitem.setStatus(daChargeItem.getStatus());
			}
			dbitem.setDateBeginRecv(dateBeginRecv);
			dbitem.setDateEndRecv(dateEndRecv);
			dbitem.setPriceRecv(daChargeItem.getPriceRecv());
			dbitem.setPriceActual(daChargeItem.getPriceActual());
			dbitem.setChargeBillRecord(dbChargeBillRecord);
			genericService.merge(dbitem);
			dbChargeItems.add(dbitem);
		}
		
		/**额外费用的处理**/
		if (extraFee != null && extraFee.size() > 0) {
			for (DaChargeItem chargeItem : extraFee) {
				DaChargeItem dbChargeItem = new DaChargeItem();
				dbChargeItem.setPriceActual(chargeItem.getPriceActual());
				dbChargeItem.setPriceRecv(chargeItem.getPriceActual()); //额外费用计算应收和实际应收一样
				dbChargeItem.setDateBeginRecv(dateBeginRecv);
				dbChargeItem.setDateEndRecv(dateEndRecv);
				dbChargeItem.setName(chargeItem.getName());
				dbChargeItem.setCreateChargeTime(new Date());
				dbChargeItem.setRoom(dbRoom);
				dbChargeItem.setChargeType(DaChargeItem.CHARGE_TYPE_CUSTOM);
				dbChargeItem.setChargeBillRecord(dbChargeBillRecord);
				dbChargeItem.setStatus(DaChargeItem.STATUS_CONFIRMED);
				dbChargeItem = genericService.merge(dbChargeItem);
				dbChargeItems.add(dbChargeItem);
			}
		}
	
		dbChargeBillRecord.setChargeItems(dbChargeItems);
		
	}
	
	/**
	 * 设置feeRecord 集中式 收租页面生成网上收租单
	 * @param model
	 * @param order
	 * @param record
	 */
	private RentalOrder setFeeRecord(Fee model, RentalOrder order, FeeRecord record,List<FeeAddition> extraFee,BigDecimal depositRecv, BigDecimal depositActual) {
		order = new RentalOrder();
		record.setId(model.getFeeRecordId());
		record = genericService.load(record);
		if(record==null){
			throw new ApplicationException("不存在信用记录");
		}
		
		BigDecimal amountActual = model.getAmountActual().setScale(2, RoundingMode.HALF_UP);
		BigDecimal amountRecv  = model.getAmountRecv().setScale(2, RoundingMode.HALF_UP);
		BigDecimal balance = model.getBalance().setScale(2, RoundingMode.HALF_UP);
		BigDecimal rental = model.getRental().setScale(2, RoundingMode.HALF_UP);
		String startDate = DateTimeUtil.completeDateTime(model.getDateBeginRecv());
		String endDate = DateTimeUtil.completeDateTime(model.getDateEndRecv());
		
		record.setRentalCalc(model.getRentalCalc());
		record.setId(model.getFeeRecordId());
		record.setAmountActual(amountActual);
		record.setAmountRecv(amountRecv);
		record.setRoom(model.getRoom());
		record.setBalance(balance);
		record.setRental(rental);
		record.setDateBeginRecv(startDate);
		record.setDateEndRecv(endDate);
		record.setStatus(FeeRecord.FEE_STATUS_RENT_TODO);
		Room room = model.getRoom();
		room = genericService.load(room);
		record.setRoom(room);
		record.setRemark(model.getRemark());
		
		if(room!=null && room.getAgreement()!=null ){
			record.setTenantUser(room.getAgreement().getTenantUser());
			if(room.getAgreement().getFees().size()>=1){
				//设置上次余额
				Fee fee = room.getAgreement().getFees().get(0);
				if(fee!=null){
					record.setPrevBalance(fee.getBalance());
				}
			}
		}
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		record.setLandlordUser(landlordUser.getOwnerUser());
		
		List<FeeAdditionRecord> feeAdditionRecords =new ArrayList<FeeAdditionRecord>();
		List<FeeAddition> feeAdditions = model.getFeeAdditions();
		feeAdditions = feeAdditions==null?new ArrayList<FeeAddition>():feeAdditions;
		
		Meter fixedMeter = genericService.load(Meter.class, 2);
		if( fixedMeter == null ){
			fixedMeter = new Meter();
		}
		
		for (FeeAddition feeAddition : feeAdditions) {
			FeeAdditionRecord additionRecord = new FeeAdditionRecord();
			FeeRuleCfg feeRuleCfg = feeAddition.getFeeRuleCfg();
			additionRecord.setFeeRuleCfg(feeRuleCfg);
			Meter meter1 = feeAddition.getMeter1()==null?fixedMeter:feeAddition.getMeter1();
			Meter meter2 = feeAddition.getMeter2()==null?fixedMeter:feeAddition.getMeter2();
			additionRecord.setMeter1(meter1);
			additionRecord.setMeter2(meter2);
			additionRecord.setName(feeAddition.getName());
			additionRecord.setPriceActual(feeAddition.getPriceActual());
			additionRecord.setPriceRecv(feeAddition.getPriceRecv().setScale(2, RoundingMode.HALF_UP));
			additionRecord.setStatus(feeAddition.getStatus());
			feeAdditionRecords.add(additionRecord);
		}
		
		/*额外费用处理*/
		FeeRuleCfg extraFeeRuleCfg = genericService.load(FeeRuleCfg.class, FeeRuleCfg.FEE_RULE_CFG_EXTRA);
		if( extraFee!=null && extraFee.size() > 0 ){
			for (FeeAddition feeAddition : extraFee) {
				FeeAdditionRecord additionRecord = new FeeAdditionRecord();
				additionRecord.setName(feeAddition.getName());
				additionRecord.setFeeRuleCfg(extraFeeRuleCfg);
				additionRecord.setMeter1(fixedMeter);
				additionRecord.setMeter2(fixedMeter);
				additionRecord.setPriceActual(feeAddition.getPriceActual());
				additionRecord.setPriceRecv(feeAddition.getPriceActual());
				additionRecord.setFeeRecord(record);
				feeAdditionRecords.add(additionRecord);
			}
		}
		
		/*押金处理*/
		if (room!=null && room.getAgreement()!=null && (room.getAgreement().getFees() == null || room.getAgreement().getFees().size() == 0)) {
			room.setNeedAddDeposit(true);
			depositActual = depositActual==null?depositRecv:depositActual;
			//修改押金金额                                                    
			record.setDepositActual(depositActual);
		}
	
		
		List<FeeAdditionRecord> dbFeeAdditionRecords = record.getFeeAdditionRecords();
		if(dbFeeAdditionRecords==null){
			dbFeeAdditionRecords = new ArrayList<FeeAdditionRecord>();
		}
		dbFeeAdditionRecords.clear();
		dbFeeAdditionRecords.removeAll(dbFeeAdditionRecords);
		dbFeeAdditionRecords.addAll(feeAdditionRecords);
		record.setFeeAdditionRecords(dbFeeAdditionRecords);
		
		order.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		order.setOrderState(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
		
		order.setFeeRecord(record);
		return order;
	}
	
	
	/**
	 * 集中式
	 * 根据页面传递信息，确认资金确认对象信息
	 * @param vo
	 * @return
	 */
	public RentalOrder getRentalOrder(ConfirmMoneyVO vo){
		
		RentalOrder order = new RentalOrder();
		order.setOrderType(RentalOrder.ORDERTYPE_RENTAL);
		order.setOrderState(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
		
		FeeRecord record = new FeeRecord();
		record.setId(vo.getFeeRecordId());
		record = genericService.load(record);

		//实收总额
		BigDecimal amountActual = vo.getTotalPriceTrue();
		//应收总额
		BigDecimal amountRecv = vo.getTotalPrice();
		
		amountActual = amountActual==null?amountRecv:amountActual;
		record.setAmountActual(amountActual);
		record.setAmountRecv(amountRecv);
		record.setBalance(vo.getBalance());
		record.setDateBeginRecv(vo.getStartDate());
		record.setDateEndRecv(vo.getEndDate());
		
		//order费用改为实收总额
		order.setTotalFee(amountActual);
		Room room = new Room();
		room.setId(vo.getId());
		room = genericService.load(room);
		record.setRoom(room);
		
		if(room!=null && room.getAgreement()!=null ){
			record.setTenantUser(room.getAgreement().getTenantUser());
			if(room.getAgreement().getFees().size()>=1){
				//设置上次余额
				Fee fee = room.getAgreement().getFees().get(0);
				if(fee!=null){
					record.setPrevBalance(fee.getBalance());
				}
			}
		}
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		record.setLandlordUser(landlordUser.getOwnerUser());
		
		
		record.setStatus(FeeRecord.FEE_STATUS_RENT_TODO); //设置状态
		
		List<ConfirmMoneyItemVO> items = vo.getItems();
		
		List<FeeAdditionRecord> feeAdditionRecords =new ArrayList<FeeAdditionRecord>();
		
		 //不用全部传过来
		for (ConfirmMoneyItemVO item : items) {
			//其它费用明细 只需要meter1 meter2
			if(item.getFeeType() != ConfirmMoneyItemVO.TYPE_ROOM.intValue() && item.getFeeType() != ConfirmMoneyItemVO.TYPE_DEPOSIT.intValue()){
				FeeRuleCfg feeRuleCfg = new FeeRuleCfg();
				feeRuleCfg.setId(item.getRuleCfgId());
				
				FeeAdditionRecord addition = new FeeAdditionRecord();
				addition.setFeeRuleCfg(feeRuleCfg);
				
				Meter meter1 = new Meter();
				meter1.setId(item.getPrMeterId());
				addition.setMeter1(meter1);
				Meter meter2 = new Meter();
				meter2.setId(item.getCurMeterId());
				addition.setMeter2(meter2);
				
				//每一项所收取的费用
				addition.setPriceRecv(item.getPriceRecv());
				addition.setPriceActual(item.getPriceActual());
				addition.setName(item.getName());
				addition.setStatus(item.getStatus());
				addition.setFeeRecord(record);
				feeAdditionRecords.add(addition);
				
			}else if (item.getFeeType() == ConfirmMoneyItemVO.TYPE_ROOM.intValue() ){
				////得到房租 实际收取费用 只会执行一次
				record.setRental(item.getPriceActual()); 
			}
		}
		
		List<FeeAdditionRecord> dbFeeAdditionRecords = record.getFeeAdditionRecords();
		if(dbFeeAdditionRecords==null){
			dbFeeAdditionRecords = new ArrayList<FeeAdditionRecord>();
		}
		dbFeeAdditionRecords.clear();
		dbFeeAdditionRecords.addAll(feeAdditionRecords);
		record.setFeeAdditionRecords(dbFeeAdditionRecords);
		
		order.setFeeRecord(record);
		
		return order;
	}
	
	/**
	 * 查询房间 可获取以下状态的房间：已生成收租单 未成生收租单
	 * 此外，如果说是已生成收租单的，展示需要按收租单的笔数来展示房间
	 * 实际单在查询已生成时，查询的是定单列表，而非房间列表
	 * @param model
	 * @param status
	 * @param userName
	 * @return
	 */
	@Rest(type = "search")
	public List<ConfirmMoneyVO>  searchRooms(DaRoom model,Integer status,String userName){
		
		DaSuite suite = new DaSuite();
		suite.setName(model.getName());
		suite.setRentState(DaSuite.RENTSTATE_RENTED);
		
		Integer  chargeState = null;
		//未交租已交租状态设置
		if (model.getHasPaid() != null) {
			chargeState = model.getHasPaid() ? 0 : 1;
		}
		
		//未生成    查询未缴费的房间   已交租和已生成的缴费与否均查询出来(因为有可能生成下一周期的)4.1-12.1
		if(status!=null && status.equals(0)){
			chargeState = 1;
		}
		
		PageInfo<DaRoom> pageInfo =daSuiteService.searchRoom(suite, userName, chargeState, null);
		
		List<ConfirmMoneyVO> resultRooms = null;
		
		if(null != pageInfo){
			resultRooms = new ArrayList<ConfirmMoneyVO>();
			List<ConfirmMoneyItemVO> items = null;
			
			for (DaRoom daRoom : pageInfo.getData()) {
					//存放转换后的item
				 	items = new ArrayList<ConfirmMoneyItemVO>();
				 	//存放未转换的item
					List<DaChargeItem> itemls = new ArrayList<DaChargeItem>();
					
					List<DaChargeBillRecord> chargeBillRecords = daRoom.getAgreement().getChargeBillRecords();
					//检查
					if(chargeBillRecords==null || chargeBillRecords.size()==0)continue;
					//拿到当彰的record
					DaChargeBillRecord daChargeBillRecord = chargeBillRecords.get(0);
					//当前的record是否存在收租单
					RentalOrder hasOrder = getRentalOrderBy(daChargeBillRecord);
					if(status==2){
						if( hasOrder==null){
							continue;
						}
					}else if (status==1){
						RentalOrder roomLastOrder = getDaRoomLastPaidOrder(daRoom);
						if(roomLastOrder==null){
							continue;
						}else{
							hasOrder = roomLastOrder;
							daChargeBillRecord = hasOrder.getChargeBillRecord();
							if(daChargeBillRecord==null)continue;
							if(daChargeBillRecord.getPrevBalance()==null){
								daChargeBillRecord.setPrevBalance(getPaidRoomPreBalanc(daRoom));
							}
						}
					}else if((status==0 && hasOrder != null)||(status==0&&daRoom.getHasPaid())){
						continue;
					}
					
					itemls =daChargeBillRecord.getChargeItems();
					for (DaChargeItem item : itemls) {
						items.add(getVoItem(item));
					}
					//封装结果集
					resultRooms.add(getVo(daRoom,items,hasOrder,daChargeBillRecord));
			}
		}
		return resultRooms;
	}

	
	/**
	 * 分散式，根据billRecord查询收租单
	 * @param daChargeBillRecord
	 * @return
	 */
	private RentalOrder getRentalOrderBy(DaChargeBillRecord daChargeBillRecord) {
		RentalOrder order = new RentalOrder();
		order.setChargeBillRecord(daChargeBillRecord);
		PageInfo<RentalOrder> searchByModel = genericService.searchByModel(order, Condition.DEFAULT);
		List<RentalOrder> data = searchByModel.getData();
		if (data!=null && data.size()>0) {
			return data.get(0);
		}
		return null;
	}
	

	/**
	 * 封装查询条件Daroom
	 * @param model
	 * @param status
	 * @param userName
	 * @param qlInfo
	 */
	@SuppressWarnings("unused")
	private void setSearchCondition(DaRoom model, Integer status,
			String userName, QLInfo qlInfo) {
		String ql = "select a from "+ DaRoom.class.getName()+" a  where 1=1";
		ql += " and a.agreement is not null and a.agreement.tenantUser is not null";
		if(StringUtils.isNotEmpty(userName)){
			ql += " and a.agreement.tenantUser.name like ?";
			qlInfo.addParam("%"+userName.trim()+"%");
		}
	
		if(StringUtils.isNotEmpty(model.getName()))
		{
			ql += " and a.suite.address is not null and (a.suite.address.name like ? or a.name like ? or a.suite.name like ?)";
			qlInfo.addParam("%"+model.getName()+"%");
			qlInfo.addParam("%"+model.getName()+"%");
			qlInfo.addParam("%"+model.getName()+"%");
		}
		ql+= " and size(a.agreement.chargeBillRecords) > 0  ";
		
		//为了避免admin进来时，把全部都查出来。
		LandlordUser landlordUser = landlordUserService.getLoginUser();
		Integer landlordUserId = landlordUser.getId();
		ql += " and a.landlordUser.id = ?";
		qlInfo.addParam(landlordUserId);
		qlInfo.setPageInfo(0, 500, null, null);
		qlInfo.setQl(ql);
	}

	
	/**
	 * 封装集中式的资金确认的vo对象
	 * @param room
	 * @param voItems
	 * @param hasOrder
	 * @param fee
	 * @return
	 */
	public ConfirmMoneyVO getVo(Room room,List<ConfirmMoneyItemVO> voItems,RentalOrder hasOrder,Fee fee){
		ConfirmMoneyVO vo = new ConfirmMoneyVO();
		if(voItems==null)return null;
		String roomName = room.getName();
		vo.setName(roomName);
		//Fee fee = room.getReceivableFee();
		vo.setStartDate(getDataStr(fee.getDateBeginRecv()));
		vo.setEndDate(getDataStr(fee.getDateEndRecv()));
		vo.setId(room.getId()); 
		vo.setFeeRecordId(fee.getFeeRecordId());
		
		if(null !=hasOrder){
			vo.setRentalOrderId(hasOrder.getId());
			vo.setOrderState(hasOrder.getOrderState());
			//总额在fee中可以取到
		}
		
		String tenUserName = "";
		try{
			tenUserName = room.getAgreement().getTenantUser().getName();
			vo.setTenantUserId(room.getAgreement().getTenantUser().getId());
		}catch(Exception e){
			logger.error(e.getMessage()+":已出租的户间，用户信息不明确");
		}
		vo.setTenUserName(tenUserName);
	
		//除了额外费用外，再加入房租
		BigDecimal fz = fee.getRental()==null?new BigDecimal(0):fee.getRental();
		ConfirmMoneyItemVO voitem = new ConfirmMoneyItemVO();
		voitem.setId(-1);
		voitem.setName("房租");
		voitem.setEndDate(getDataStr(fee.getDateEndRecv()));
		voitem.setStartDate(getDataStr(fee.getDateBeginRecv()));
		voitem.setPriceActual(fz);
		voitem.setPriceRecv(fee.getRentalCalc());
		voitem.setPrMeter(new BigDecimal(0));
		voitem.setCurMeter(new BigDecimal(0));
		voitem.setFeeType(ConfirmMoneyItemVO.TYPE_ROOM);
		voItems.add(voitem);
		
		BigDecimal amountActual = fee.getAmountActual();
		BigDecimal amountRecv = fee.getAmountRecv();
		
		BigDecimal deposit = room.getDeposit();
		
		FeeRuleCfg extraFeeRuleCfg = genericService.load(FeeRuleCfg.class, FeeRuleCfg.FEE_RULE_CFG_EXTRA);
		//产生押金
		if(room.getNeedAddDeposit()!=null &&room.getNeedAddDeposit().booleanValue()){
			ValidAgreement agreement = room.getAgreement();
			deposit= fee.getDepositActual();
			if(deposit==null){
				try{
					String deposit2 =agreement.getDeposit();
					deposit = new BigDecimal(deposit2).setScale(2,RoundingMode.HALF_UP);
				}catch(Exception e){
					deposit = new BigDecimal(0);
				}
			}
			ConfirmMoneyItemVO depositItem = new ConfirmMoneyItemVO();
			depositItem.setName("押金");
			depositItem.setEndDate(agreement.getRentEndDate());
			depositItem.setStartDate(agreement.getRentBeginDate());
			depositItem.setPriceActual(deposit);
			depositItem.setPriceRecv(deposit);
			depositItem.setPrMeter(new BigDecimal(0));
			depositItem.setCurMeter(new BigDecimal(0));
			depositItem.setFeeType(ConfirmMoneyItemVO.TYPE_DEPOSIT);
			depositItem.setRuleCfgId(extraFeeRuleCfg.getId());
			voItems.add(depositItem);
			if(amountActual==null){
				amountRecv = amountRecv.add(deposit);
			}
		}
		
		vo.setItems(voItems);
		vo.setItemCount(voItems.size());
		
		amountActual = amountActual==null?amountRecv:amountActual;
		vo.setTotalPriceTrue(amountActual);
		vo.setTotalPrice(amountRecv);
		
		//上次余额
		BigDecimal prevBalance = fee.getPrevBalance();
		prevBalance = prevBalance==null?new BigDecimal(0):prevBalance;
		vo.setPrevBalance(prevBalance);
		
		BigDecimal balance = fee.getBalance();
		vo.setBalance(balance);
		
		return vo;
	}
	
	/**
	 * 封装集中式的itemVo对象  注意期meter与分散式是反过来的
	 * @param feeAddition
	 * @param fee
	 * @return
	 */
	private ConfirmMoneyItemVO getVoItem(FeeAddition feeAddition,Fee fee ) {
		ConfirmMoneyItemVO  voItem = new ConfirmMoneyItemVO();
		voItem.setId(feeAddition.getId());
		voItem.setStatus(feeAddition.getStatus());
		FeeRuleCfg ruleCfg = feeAddition.getFeeRuleCfg();
		try{
			FeeRuleCfgDesc feeRuleCfgDesc = ruleCfg.getFeeRuleCfgDesc();
			FeeRuleType type = feeRuleCfgDesc.getType();
			String name = feeRuleCfgDesc.getName();
			String feeAddtionName = feeAddition.getName();
			if(StringUtils.isBlank(feeAddtionName)){
				voItem.setName(name);
			}else{
				voItem.setName(feeAddtionName);
			}
			
			voItem.setRuleCfgId(ruleCfg.getId());
			if(type.equals(FeeRuleType.meter)){
				Meter meter1 = feeAddition.getMeter1();
				Meter meter2 = feeAddition.getMeter2();
				BigDecimal  prMeter = meter2== null?new BigDecimal(0):feeAddition.getMeter2().getCount();
				BigDecimal  curMeter = meter1== null?new BigDecimal(0):feeAddition.getMeter1().getCount();
				voItem.setPrMeter(prMeter);
				voItem.setCurMeter(curMeter);
				Integer prMeterId = meter2==null?0:meter2.getId();
				Integer currMeterId = meter1==null?0:meter1.getId();
				voItem.setPrMeterId(prMeterId);
				voItem.setCurMeterId(currMeterId);
				
				if(	meter1!=null && meter2 !=null ){
					voItem.setStartDate(getDataStr(meter2.getCheckTime()));
					voItem.setEndDate(getDataStr(meter1.getCheckTime()));
				}
				
				voItem.setFeeType(ConfirmMoneyItemVO.TYPE_METER);
			 }else{
				voItem.setPrMeter(new BigDecimal(0));
				voItem.setCurMeter(new BigDecimal(0));
				voItem.setStartDate(getDataStr(fee.getDateBeginRecv()));
				voItem.setEndDate(getDataStr(fee.getDateEndRecv()));
				voItem.setFeeType(ConfirmMoneyItemVO.TYPE_OTHER);
			}
			voItem.setPriceRecv(feeAddition.getPriceRecv());
			voItem.setPriceActual(feeAddition.getPriceActual()==null?feeAddition.getPriceRecv():feeAddition.getPriceActual());
			return voItem;
		}catch(Exception e){
			return null;
		}
	}
	
	/**
	 * 封装分散式的vo对象
	 * @param daRoom
	 * @param items
	 * @param count
	 * @param order
	 * @return
	 */
	private ConfirmMoneyVO getVo(DaRoom daRoom ,List<ConfirmMoneyItemVO> items,RentalOrder order,DaChargeBillRecord record){
		ConfirmMoneyVO vo = new ConfirmMoneyVO();
		vo.setId(daRoom.getId());
		
		DaSuite suite = daRoom.getSuite();
		String adress = suite.getAddress().getName();
		vo.setAdressName(adress);
		if(suite.getRentType().equals(DaSuite.RENT_TYPE_ENTIRE)){
			vo.setName(suite.getName());
		}else{
			vo.setName(suite.getName()+"-"+daRoom.getName());
		}
		vo.setFeeRecordId(record.getId());
		vo.setItems(items);
		vo.setItemCount(items.size());
		
		vo.setTenUserName(daRoom.getAgreement().getTenantUser().getName());
		vo.setTenantUserId(daRoom.getAgreement().getTenantUser().getId());
		if(null != order){
			vo.setRentalOrderId(order.getId());
			vo.setOrderState(order.getOrderState());
		}
		BigDecimal prevBalance = record.getPrevBalance();
		if(prevBalance==null){
			prevBalance = paidNoticeService.getRoomBlance(daRoom);
		}
		
		BigDecimal amountActual = record.getAmountActual();
		BigDecimal amountRecv = record.getAmountRecv();
		
		if(amountRecv==null){
			amountRecv = new BigDecimal(0);
			for (ConfirmMoneyItemVO confirmMoneyItemVO : items) {
				amountRecv = amountRecv.add(confirmMoneyItemVO.getPriceRecv());
			}
		}
		amountActual = amountActual==null?amountRecv:amountActual;
		
		vo.setTotalPrice(amountRecv);
		vo.setTotalPriceTrue(amountActual);
		vo.setPrevBalance(prevBalance);
		vo.setBalance(record.getBalance());
		
		vo.setStartDate(this.getDataStr(record.getDateBeginRecv()));
		vo.setEndDate(this.getDataStr(record.getDateEndRecv()));
		
		return vo;
	}
	
	
	/**
	 * 封装分散式的itemvo对象
	 * @param item
	 * @return
	 */
	private ConfirmMoneyItemVO getVoItem(DaChargeItem item) {
		ConfirmMoneyItemVO voItem;
		voItem = new ConfirmMoneyItemVO();
		voItem.setId(item.getId());
		voItem.setName(item.getName());
		voItem.setStartDate( getDataStr(item.getDateBeginRecv()) );
		voItem.setEndDate( getDataStr(item.getDateEndRecv()) );
		
		BigDecimal  prMeter = item.getMeter1()== null?new BigDecimal(0):item.getMeter1().getCount();
		BigDecimal  curMeter = item.getMeter2()== null?new BigDecimal(0):item.getMeter2().getCount();
		voItem.setCurMeter(curMeter);
		voItem.setPrMeter(prMeter);
		Integer prMeterId = item.getMeter1()==null?0:item.getMeter1().getId();
		Integer curMeterId = item.getMeter2()==null?0:item.getMeter2().getId();
		voItem.setPrMeterId(prMeterId);
		voItem.setCurMeterId(curMeterId);
		
		voItem.setPriceRecv(item.getPriceRecv());
		BigDecimal actual = item.getPriceActual();
		actual=actual==null?item.getPriceRecv():actual;
		voItem.setPriceActual(actual);
		voItem.setFeeType(item.getChargeType());
		voItem.setStatus(item.getStatus());
		return voItem;
	}
	
	/**
	 * 格式化日期为字符串
	 * @param date
	 * @return
	 */
	public String getDataStr(Date date){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			return sdf.format(date);
		} catch (Exception e) {
			return "";
		}
	}
	
	/**
	 * 把字符串转为日期
	 * @param date
	 * @return
	 */
	public String getDataStr(String date){
		if(StringUtils.isEmpty(date)){
			return "";
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			Date d = sdf.parse(date);
			return sdf.format(d);
		} catch (Exception e) {
			return "";
		}
	}
	
	/**
	 * 查询房间当前合约的最后一笔交费记录。
	 * @param model
	 * @return
	 */
	public DaChargeBill getLastChargeBillBy(DaAgreement agreement){
		DaChargeBill serchModel = new DaChargeBill();
		if(agreement != null){
			serchModel.setAgreement(agreement);
		}
		Condition condition = new Condition();
		condition.setSort("id");
		condition.setDir("desc");
		DaChargeBill dbChargeBill = genericService.searchByModel(serchModel, condition).getData(0);
		return dbChargeBill;
	}
	
	/**
	 * 获取已支付房间的上次支付余额
	 * @param room
	 * @return
	 */
	public BigDecimal getPaidRoomPreBalanc(DaRoom room){
		if(room.getAgreement()==null)return new BigDecimal(0);
		DaChargeBill example = new DaChargeBill();
		example.setAgreement(room.getAgreement());
		Condition condition = new Condition();
		condition.setSort("id");
		condition.setDir("desc");
		DaChargeBill dbChargeBill = genericService.searchByModel(example, condition).getData(1);
		
		if(dbChargeBill != null && dbChargeBill.getBalance()!=null){
			return dbChargeBill.getBalance();
		}else{
			return new BigDecimal(0);
		}
	}
	
	
	
	public boolean repairPrevBalance(){
		
		String ql = " from "+RentalOrder.class.getName()+" a " ;
		ql += " left join a.feeRecord b left join b.room c where a.orderState = 3 and a.chargeBillRecord is null and a.feeRecord is not null and (a.roomType is null or a.roomType<>0) "
				+ "and b.prevBalance is null and b.room is not null and c.agreement is not null";
		
		QLInfo qlInfo = new QLInfo();
		qlInfo.setQl(ql);
		int count = genericService.getCount(qlInfo, false);
		int goCount = 0;
		for(int i=0;i<count;i+=1000){
			qlInfo.setFirstResult(0);
			qlInfo.setMaxResults(1000);
			List<RentalOrder> orders = genericService.searchByQl(qlInfo).getData();
			if(orders != null && orders.size() > 0 ){
				goCount = getInstance().repairingPrevBalance(orders);
			}
		}
		if(goCount!=0){
			repairPrevBalance();
		}
		return true;
	}
	
	@Transactional
	public int repairingPrevBalance( List<RentalOrder> orders ){
		int count = 0;
		for (RentalOrder rentalOrder : orders) {
			try{
				Room room = rentalOrder.getRoom();
				if(room == null || room.getAgreement()==null)continue;
				FeeRecord feeRecord = rentalOrder.getFeeRecord();
				if(feeRecord == null || feeRecord.getPrevBalance() !=null )continue;
				
				List<Fee> fees =room.getAgreement().getFees();
				BigDecimal prevBalance = BigDecimal.valueOf(0);
				if(fees != null && fees.size() > 2){
					//已交租的情况
					if(rentalOrder.getOrderState()!=null && rentalOrder.getOrderState().intValue()==3){
						prevBalance = fees.get(1).getBalance();
					}else{
						//未生成和已生成
						prevBalance = fees.get(0).getBalance();
					}
				}else if(fees != null && fees.size() == 2){
					//第一次交费
					prevBalance = fees.get(0).getBalance();
				}
				feeRecord = genericService.load(feeRecord);
				feeRecord.setPrevBalance(prevBalance);
				em.persist(feeRecord);
				count++;
			}catch(Exception e){
				logger.error("修复rentalOrder下feeRecord的PreBalance失败，rentalOrderId:" + rentalOrder.getId(), e);
			}
		}
		System.out.println("------------------------------------:"+count);
		em.flush();
		em.clear();
		return count;
	}
	
	/**
	 * 主要根据order的生成状态查询房间
	 * @param model
	 * @param status
	 * @param tenantUserName
	 * @return
	 */
	public List<Room> searchRentedRoomsWithOrderStatusAnd(Room model,Integer status,String tenantUserName ){
		
		QLInfo qlInfo = new QLInfo();
		
		Building building = null;
		if(model.getBuilding()!=null && model.getBuilding().getId()!=null){
			building = genericService.load(Building.class, model.getBuilding().getId());
		}
		
		//确实房间已出租且拥有效合约
	    String qlStr = "select a from "+Room.class.getName()+" a left join a.agreements b with b.agreementState = 0 where a.rentState = ?";
	    qlInfo.addParam(Room.RENT_STATE_ALREADY);
	    
	    //确定所属楼层 注：floorId为0时查全部 层,floorId为空时查第一层(默认)
	    if(building != null){
	    	qlStr += " and a.building.id = ? ";
		    qlInfo.addParam(model.getBuilding().getId());
		    if (model.getBuildingFloor() != null && model.getBuildingFloor().getId() != null) {
				if (model.getBuildingFloor().getId() != 0) {
					qlStr += " and a.buildingFloor.id = ?";
					qlInfo.addParam(model.getBuildingFloor().getId());
				} 
			} else {
				 qlStr += " and a.buildingFloor.id = ?";
				 qlInfo.addParam(building.getBuildingFloors().get(0).getId());
			}
	    }
	    //查询已生成收租单 且 该收租单未交租成功的
	    if(status != null && status.equals(2)){
	    	qlStr += "  and exists (select c.id from "+RentalOrder.class.getName()+" c where c.room is not null and c.room.id= a.id  and (c.orderState=? or c.orderState=?))";
	    	qlInfo.addParam(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
	    	qlInfo.addParam(RentalOrder.ORDER_STATE_PAYING);
	    	/*qlInfo.addParam(RentalOrder.ORDER_STATE_PAYMENTED);*/
	    //查询已生成收租单 且 收租单交租成功的
	    }else if (status != null && status.equals(1)){
	    	qlStr += "  and exists (select c.id from "+RentalOrder.class.getName()+" c where c.room is not null and c.room.id= a.id  and (c.orderState=? or c.orderState = ?) )";
	    	qlInfo.addParam(RentalOrder.ORDER_STATE_SUCCESS);
	    	qlInfo.addParam(RentalOrder.ORDER_STATE_PAYMENTED);
	    	
	    //查询本周期未生成收租 且  未缴费的房间 (未缴费:不具备fees或具备fees但房租的结束日期小于等于今天的日期)
	    }else if (status != null && status.equals(0)){
	    	//不存在待收的收租单
	    	qlStr += "  and not exists (select c.id from "+RentalOrder.class.getName()+" c where c.room is not null and c.room.id= a.id  and (c.orderState=? or c.orderState=? or c.orderState=? )) ";
	    	qlInfo.addParam(RentalOrder.ORDER_STATE_WAITING_PAYMENT);
	    	qlInfo.addParam(RentalOrder.ORDER_STATE_PAYING);
	    	qlInfo.addParam(RentalOrder.ORDER_STATE_PAYMENTED);
	    	//本周期未缴费
	    	qlStr += " and not exists (select d.id from b.fees d where substr(date_add_interval(d.dateEndRecv,-ifnull(b.advanceNum, 3) ),1,10) >= substr(?, 1, 10) and d.feeType = ? )  ";
	    	qlInfo.addParam(DateTimeUtil.throwTimeForDate(new Date()));
	    	qlInfo.addParam(Fee.FEE_TYPE_RENTAL);
	    	
	    }
	    
	    //房间名称
	    if (StringUtils.isNotEmpty(model.getName())) {
	    	qlStr += " and a.name like ? ";
	    	qlInfo.addParam("%" + model.getName().trim() + "%");
		}
	    
	    //租客
		if (StringUtils.isNotEmpty(tenantUserName)) {
			Session session = (Session)em.getDelegate();
			qlStr += " and ( (a.rentType = ? and b is not null and b.tenantUser.name like ?) or a.rentType=? )";
			qlInfo.addParam(Room.RENT_TYPE_ENTIRE);
			qlInfo.addParam("%" + tenantUserName + "%");
			qlInfo.addParam(Room.RENT_TYPE_SUB);
			Filter filter = session.enableFilter("tenantUserNameFilter");
			filter.setParameter("tenantUserName", "%" + tenantUserName + "%");
		}
		
		
		qlInfo.setDisablePermissionFilter(false);
	    qlInfo.setQl(qlStr);
	    PageInfo<Room> pageInfo = genericService.searchByQl(qlInfo);
	  
	    return pageInfo.getData();
	}
	
}
